////////////////////////////////////
///////// GLOBAL VARIABLES /////////
////////////////////////////////////

// Constants
var _PADDING = 200; // The pixel padding for the map's sides
var _SCALEFACTORS = [0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6];

// Starting parameters for the map
var _mapWidth = 30;
var _mapHeight = 30;

// The starting scale
var _currentScale = 3;

// The tile size (loaded from the file)
var _TILEFILE = "tile.svg";
var _tileWidth = 0;
var _tileHeight = 0;

// Used for calculating delta values for mouse movement
var _lastX = 0;
var _lastY = 0;

// The current tool
//   0 - Cursor
//   1 - Drag
var _TOOLNAMES = ["Cursor", "Drag"];
var _curTool = -1;

// The last received mouse events
var _lastDown = "None";
var _lastClick = "None";

// Selected coordinates on the map
var _selectedU = -1;
var _selectedV = -1;

////////////////////////////////////
///////////// MAP DATA /////////////
////////////////////////////////////

function Tile(selected)
{
	this.selected = selected;
}

////////////////////////////////////
////////// INITIALIZATION //////////
////////////////////////////////////

// Performs all of the initialization steps
function initDaedalus()
{
	// Set the current tool to the cursor
	selectTool(0);
	// Set event listeners
    document.onmousedown = onMouseDown;
    document.onmouseup = onMouseUp;
	document.onclick = onClick;
	// Read the tile file
	loadTile();
	// Draw the map
	drawMap();
	
}
// Loads the tile file and sets the width and height global variables
function loadTile()
{
	// Load the tile file and get its width and height
	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("GET", _TILEFILE, false);
	xmlhttp.send();
	var xmlDoc = xmlhttp.responseXML;
	_tileWidth = parseInt(xmlDoc.getElementsByTagName("svg")[0].getAttribute("width"));
	_tileHeight = parseInt(xmlDoc.getElementsByTagName("svg")[0].getAttribute("height"));
}

////////////////////////////////////
////////// TOOL SELECTION //////////
////////////////////////////////////

// Resets the currently selected tool and image
function resetToolSelection()
{
	_curTool = -1;
	document.getElementById("buttonCursor").src = "buttonCursor.png";
	document.getElementById("buttonDrag").src = "buttonDrag.png";
}

// Selects the cursor as the current tool (and modifies the image)
function selectTool(toolNum)
{
	// Reset the selection
	resetToolSelection()
	_curTool = toolNum;
	toolName = _TOOLNAMES[toolNum]
	document.getElementById("button" + toolName).src = "button" + toolName + "Selected.png";
}

////////////////////////////////////
/////////// MOUSE EVENTS ///////////
////////////////////////////////////

// Records the name of the last clicked object
// Params:
//    eventName - The name of the event to record
function registerClick(eventName)
{
	_lastClick = eventName;
}

// Records the name of the last mouseDown object
// Params:
//    eventName - The name of the event to record
function registerDown(eventName)
{
	_lastDown = eventName;
}

// Central processing for mousedown events
function onMouseDown(e)
{
	if (e == null) 
			e = window.event; 
			
	// Cancel out any text selections
	document.body.focus();
	
	switch(_lastDown)
	{
		case "buttonPlus":
		case "buttonMinus":
		case "buttonCursor":
		case "buttonDrag":
			break;
		default:
			switch(_curTool)
			{
				case 0: // Selector tool
					break;
				case 1: // Drag tool			
					// Grab the mouse position
					_lastX = e.clientX;
					_lastY = e.clientY;
					// Register the mouse move listener
					document.onmousemove = onMouseMove;
					// Reset the event
					_lastDown = "None";
					// prevent text selection (except IE)
					return false;
					// TODO: Get more specific here about dragging and selecting in browsers
			}
	}
	
	// Reset the event
	_lastDown = "None";
}

function onMouseMove(e)
{
	// Cancel out any text selections
	document.body.focus();

    if (e == null) 
        var e = window.event; 

	// Perform the scroll
	window.scrollBy((_lastX - e.clientX), (_lastY - e.clientY));
	_lastX = e.clientX;
	_lastY = e.clientY;
}

function onMouseUp(e)
{
	// Cancel out any text selections
	document.body.focus();
	
	// We're done with these events until the next onMouseDown
	document.onmousemove = null;
	document.onselectstart = null;
}

function onClick(e)
{
	if (e == null)
		var e = window.event;

	// Cancel out any text selections
	document.body.focus();
	
	switch(_lastClick)
	{
		case "buttonPlus":
			changeZoom(1);
			break;
		case "buttonMinus":
			changeZoom(-1);
			break;
		case "buttonCursor":
			selectTool(0);
			break;
		case "buttonDrag":
			selectTool(1);
			break;
		default:
			switch(_curTool)
			{
				case 0: // Selector tool
					// Find the UV coordinates clicked
					uvPair = screenToUV(e.clientX, e.clientY);
					_selectedU = uvPair.u;
					_selectedV = uvPair.v;
					
					// Redraw the map
					// TODO: Get smarter about this and just update the one tile
					drawMap();
					break;
				
				case 1: // Drag tool
					break;
			}
		break;
	}
	
	_lastClick = "None";
}

////////////////////////////////////
///////////// TILE MAP /////////////
////////////////////////////////////

// Computes UV coordinates from screen XY coordinates
// Params:
//    x, y - The screen coordinates
// Returns: 
//    uvPair.u and uvPair.v
function screenToUV(x, y)
{
	// Scale all of the relevant constants by the scaling factor
	var scaledWidth = _tileWidth * _SCALEFACTORS[_currentScale];
	var scaledHeight = _tileHeight * _SCALEFACTORS[_currentScale];
	var scaledPadding = _PADDING * _SCALEFACTORS[_currentScale];

	// Get the container
	var container = document.getElementById("container");
	
	// Compute the coordinates we clicked on the non-padded board
	var board_x = x + document.body.scrollLeft - (container.offsetLeft + scaledPadding);
	var board_y = y + document.body.scrollTop - (container.offsetTop + scaledPadding + ((_mapWidth - 1) * scaledHeight / 2.0));
	
	var uvPair = new Object();
	uvPair.u = Math.round((board_x / scaledWidth) - (board_y / scaledHeight));
	uvPair.v = Math.round((board_x / scaledWidth) + (board_y / scaledHeight)) - 1;
	return uvPair;
}


function drawMap()
{	
	// Fetch the container in which we'll be placing everything
	var container = document.getElementById("container");
	
	// Remove all the child nodes, if any exist
	while(container.hasChildNodes()) 
	{
		container.removeChild(container.firstChild);       
    }

	// Scale all of the relevant constants by the scaling factor
	var scaledWidth = _tileWidth * _SCALEFACTORS[_currentScale];
	var scaledHeight = _tileHeight * _SCALEFACTORS[_currentScale];
	var scaledPadding = _PADDING * _SCALEFACTORS[_currentScale];
	
	for(v = 0; v < _mapHeight; v++)
	{
		for(u = 0; u < _mapWidth; u++)
		{
			// Create the image as the background of a div (so it 
			// doesn't accidentally get selected)
			var tileDiv = document.createElement("div");
			if (u == _selectedU && v == _selectedV)
				tileDiv.style.backgroundImage = "url(tilered.svg)";
			else
				tileDiv.style.backgroundImage = "url(" + _TILEFILE + ")";
			tileDiv.style.width = scaledWidth + "px";
			tileDiv.style.height = scaledHeight + "px";
			tileDiv.style.backgroundSize = scaledWidth + "px " + scaledHeight + "px";
			tileDiv.style.border = "0px";
			tileDiv.style.position="absolute";
			// Calculate the coordinates from the (u, v) coordinates
			tileDiv.style.left = Math.round((u * scaledWidth / 2.0) + (v * scaledWidth / 2.0) + scaledPadding) + 'px';
			tileDiv.style.top = Math.round((v * scaledHeight / 2.0) - (u * scaledHeight / 2.0) + ((_mapWidth - 1) * scaledHeight / 2.0) + scaledPadding) + 'px';
			// Add the image to the container
			container.appendChild(tileDiv);
		}
	}
			
	// Calculate the resulting dimensions of the tilemap, plus padding
	var maxWidth = ((_mapWidth + _mapHeight) * scaledWidth / 2.0) + (scaledPadding * 2.0);
	var maxHeight = ((_mapWidth + _mapHeight) * scaledHeight / 2.0) + (scaledPadding * 2.0);
	container.style.width = maxWidth + 'px';
	container.style.height = maxHeight + 'px';
	
	// Center vertically
	document.getElementById("distance").style.marginBottom = '-' + Math.round(maxHeight / 2.0) + 'px'
}

// Change the zoom level within the presets
// TODO: Accommodate scroll wheel
function changeZoom(delta)
{
	_currentScale = _currentScale + delta;
	if (_currentScale >= _SCALEFACTORS.length)
	{
		_currentScale = _SCALEFACTORS.length - 1;
	}
	else if (_currentScale < 0)
	{
		_currentScale = 0;
	}
	drawMap();
}